package com.hongshu.web.service.web.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hongshu.common.core.constant.ImConstant;
import com.hongshu.common.core.domain.CountMessage;
import com.hongshu.common.core.domain.Message;
import com.hongshu.common.core.enums.MessageTypeEnum;
import com.hongshu.common.core.exception.BusinessException;
import com.hongshu.common.core.utils.ConvertUtils;
import com.hongshu.common.core.utils.RedisUtils;
import com.hongshu.web.auth.AuthContextHolder;
import com.hongshu.web.domain.entity.IdleProduct;
import com.hongshu.web.domain.entity.WebChat;
import com.hongshu.web.domain.entity.WebChatUserRelation;
import com.hongshu.web.domain.entity.WebUser;
import com.hongshu.web.domain.vo.ChatProductRelationVO;
import com.hongshu.web.domain.vo.ChatUserRelationVo;
import com.hongshu.web.domain.vo.SystemNotification;
import com.hongshu.web.factory.ChatCountMessage;
import com.hongshu.web.factory.ChatUserMessage;
import com.hongshu.web.factory.MessageFactory;
import com.hongshu.web.mapper.idle.IdleProductMapper;
import com.hongshu.web.mapper.web.WebChatMapper;
import com.hongshu.web.mapper.web.WebChatUserRelationMapper;
import com.hongshu.web.mapper.web.WebUserMapper;
import com.hongshu.web.service.web.IWebChatService;
import com.hongshu.web.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 聊天
 *
 * @author: hongshu
 */
@Service
public class WebChatServiceImpl extends ServiceImpl<WebChatMapper, WebChat> implements IWebChatService {

    @Autowired
    private WebUserMapper userMapper;
    @Autowired
    private WebChatMapper chatMapper;
    @Autowired
    private IdleProductMapper productMapper;
    @Autowired
    private WebSocketServer webSocketServer;
    @Autowired
    private WebChatUserRelationMapper chatUserRelationMapper;
    @Autowired
    private RedisUtils redisUtils;


    /**
     * 发送消息
     *
     * @param message 消息
     */
    @Override
    public void sendMsg(Message message) {
        webSocketServer.sendInfo(message);
        MessageFactory messageFactory = null;

        // 过滤发送的请求类型
        switch (message.getMsgType()) {
            case 0:
                messageFactory = new ChatCountMessage(redisUtils);
                break;
            case 1:
                messageFactory = new ChatUserMessage(webSocketServer, chatMapper, userMapper, chatUserRelationMapper);
                break;
            case 2:
                messageFactory = new ChatUserMessage(webSocketServer, chatMapper, userMapper, chatUserRelationMapper);
                break;
            default:
                break;
        }
        if (messageFactory != null) {
            messageFactory.sendMessage(message);
        }
    }

    /**
     * 获取所有聊天记录
     *
     * @param currentPage 分页
     * @param pageSize    分页数
     * @param acceptUid   接收方用户ID
     */
    @Override
    public Page<WebChat> getAllChatRecord(long currentPage, long pageSize, String acceptUid) {
//        String currentUid = WebUtils.getRequestHeader(UserConstant.USER_ID);
        String currentUid = AuthContextHolder.getUserId();
        QueryWrapper<WebChat> queryWrapper = new QueryWrapper<WebChat>()
                // 添加 product_id 为空的条件
                .isNull("product_id")
                .and(wrapper -> wrapper
                        .or(e -> e
                                .eq("send_uid", currentUid)
                                .eq("accept_uid", acceptUid)
                        )
                        .or(e -> e
                                .eq("send_uid", acceptUid)
                                .eq("accept_uid", currentUid)
                        )
                )
                .orderByAsc("timestamp");
        return this.page(new Page<>((int) currentPage, (int) pageSize), queryWrapper);
    }

    /**
     * 获取商品聊天记录
     *
     * @param currentPage 分页
     * @param pageSize    分页数
     * @param acceptUid   接收方用户ID
     */
    @Override
    public Page<WebChat> getProductChatRecord(long currentPage, long pageSize, String acceptUid, String productId) {
//        String currentUid = WebUtils.getRequestHeader(UserConstant.USER_ID);
        String currentUid = AuthContextHolder.getUserId();

        QueryWrapper<WebChat> queryWrapper = new QueryWrapper<WebChat>()
                // 添加商品ID过滤条件
                .eq("product_id", productId)
                // 使用嵌套条件处理发送者和接收者的关系
                .and(wrapper -> wrapper
                        .or(e -> e
                                .eq("send_uid", currentUid)
                                .eq("accept_uid", acceptUid)
                        )
                        .or(e -> e
                                .eq("send_uid", acceptUid)
                                .eq("accept_uid", currentUid)
                        )
                )
                .orderByAsc("timestamp");
        return this.page(new Page<>((int) currentPage, (int) pageSize), queryWrapper);
    }

    /**
     * 获取当前用户下所有聊天的用户信息
     */
    @Override
    public List<ChatUserRelationVo> getChatUserList() {
//        String currentUid = WebUtils.getRequestHeader(UserConstant.USER_ID);
        String currentUid = AuthContextHolder.getUserId();
        List<ChatUserRelationVo> result = new ArrayList<>();
        List<WebChatUserRelation> chatUserRelationList = chatUserRelationMapper
                .selectList(new QueryWrapper<WebChatUserRelation>()
                        .eq("accept_uid", currentUid)
                        .orderByDesc("timestamp")
                        .isNull("product_id"));
        if (chatUserRelationList.isEmpty()) {
            return result;
        }
        Set<String> uids = chatUserRelationList.stream().map(WebChatUserRelation::getSendUid).collect(Collectors.toSet());
        Map<String, WebUser> userMap = userMapper.selectBatchIds(uids).stream().collect(Collectors.toMap(WebUser::getId, user -> user));

        chatUserRelationList.forEach(item -> {
            ChatUserRelationVo chatUserRelationVo = ConvertUtils.sourceToTarget(item, ChatUserRelationVo.class);
            WebUser user = userMap.get(item.getSendUid());
            chatUserRelationVo.setUid(String.valueOf(user.getId()));
            chatUserRelationVo.setUsername(user.getUsername());
            chatUserRelationVo.setAvatar(user.getAvatar());
            result.add(chatUserRelationVo);
        });
        return result;
    }

    @Override
    public List<ChatProductRelationVO> getProductChatUserList() {
//        String currentUid = WebUtils.getRequestHeader(UserConstant.USER_ID);
        String currentUid = AuthContextHolder.getUserId();
        List<ChatProductRelationVO> result = new ArrayList<>();

        // 获取聊天关系列表
        List<WebChatUserRelation> chatUserRelationList = chatUserRelationMapper
                .selectList(new QueryWrapper<WebChatUserRelation>()
                        .eq("accept_uid", currentUid)
                        .orderByDesc("timestamp")
                        .isNotNull("product_id"));

        if (chatUserRelationList.isEmpty()) {
            return result;
        }

        // 获取用户信息
        Set<String> uids = chatUserRelationList.stream()
                .map(WebChatUserRelation::getSendUid)
                .collect(Collectors.toSet());
        Map<String, WebUser> userMap = userMapper.selectBatchIds(uids)
                .stream()
                .collect(Collectors.toMap(WebUser::getId, user -> user));

        // 获取商品信息
        Set<String> productIds = chatUserRelationList.stream()
                .map(WebChatUserRelation::getProductId)
                .collect(Collectors.toSet());
        Map<String, IdleProduct> productMap = productMapper.selectBatchIds(productIds)
                .stream()
                .collect(Collectors.toMap(IdleProduct::getId, product -> product));

        chatUserRelationList.forEach(item -> {
            ChatProductRelationVO chatProductRelationVO = ConvertUtils.sourceToTarget(item, ChatProductRelationVO.class);
            // 设置用户信息
            WebUser user = userMap.get(item.getSendUid());
            chatProductRelationVO.setUid(String.valueOf(user.getId()));
            chatProductRelationVO.setUsername(user.getUsername());
            chatProductRelationVO.setAvatar(user.getAvatar());

            // 设置商品信息
            IdleProduct product = productMap.get(item.getProductId());
            if (product != null) {
                chatProductRelationVO.setProductId(product.getId());
                chatProductRelationVO.setProductName(product.getTitle());
                chatProductRelationVO.setProductImage(product.getCover());
                chatProductRelationVO.setPrice(product.getPrice());
            }

            result.add(chatProductRelationVO);
        });
        return result;
    }

    /**
     * 获取所有聊天记录数量
     */
    @Override
    public CountMessage getCountMessage() {
//        String currentUid = WebUtils.getRequestHeader(UserConstant.USER_ID);
        String currentUid = AuthContextHolder.getUserId();
        String messageCountKey = ImConstant.MESSAGE_COUNT_KEY + currentUid;
        if (Boolean.FALSE.equals(redisUtils.hasKey(messageCountKey))) {
            CountMessage countMessage = new CountMessage();
            countMessage.setFollowCount(0L);
            countMessage.setCommentCount(0L);
            countMessage.setLikeOrCollectionCount(0L);
            return countMessage;
        }
        String json = redisUtils.get(messageCountKey);
        return JSONUtil.toBean(json, CountMessage.class);
    }

    /**
     * 清除聊天数量
     *
     * @param sendUid 发送方用户ID
     * @param type    类型
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clearMessageCount(String sendUid, Integer type, String productId) {
//        String currentUid = WebUtils.getRequestHeader(UserConstant.USER_ID);
        String currentUid = AuthContextHolder.getUserId();
        MessageTypeEnum messageType = MessageTypeEnum.valueOf(type);

        try {
            switch (messageType) {
                case CHAT:
                case PRODUCT_CHAT:
                    this.clearChatMessageCount(sendUid, currentUid, messageType, productId);
                    break;
                case LIKE:
                case COMMENT:
                case FOLLOW:
                    this.clearOtherMessageCount(sendUid, messageType);
                    break;
                default:
                    throw new IllegalArgumentException("Unsupported message type: " + type);
            }

            // 同步更新缓存
            this.updateMessageCountCache(sendUid, messageType);

        } catch (Exception e) {
            log.error("Clear message count failed: ", e);
            throw new BusinessException("清除消息计数失败");
        }
    }

    private void clearChatMessageCount(String sendUid, String currentUid, MessageTypeEnum type, String productId) {
        QueryWrapper<WebChatUserRelation> wrapper = new QueryWrapper<WebChatUserRelation>()
                .eq("send_uid", sendUid)
                .eq("accept_uid", currentUid);

        if (type == MessageTypeEnum.PRODUCT_CHAT) {
            wrapper.eq("product_id", productId);
        } else {
            wrapper.isNull("product_id");
        }

        WebChatUserRelation chatUserRelation = chatUserRelationMapper.selectOne(wrapper);
        if (chatUserRelation != null) {
            chatUserRelation.setCount(0);
            chatUserRelationMapper.updateById(chatUserRelation);

            // 更新缓存中的聊天消息计数
            String chatCountKey = ImConstant.MESSAGE_COUNT_KEY + currentUid + ":" + sendUid;
            redisUtils.set(chatCountKey, "0");
        }
    }

    private void clearOtherMessageCount(String sendUid, MessageTypeEnum type) {
        String messageCountKey = ImConstant.MESSAGE_COUNT_KEY + sendUid;
        String json = redisUtils.get(messageCountKey);
        CountMessage countMessage = json != null ?
                JSONUtil.toBean(json, CountMessage.class) : new CountMessage();

        // 更新缓存
        switch (type) {
            case LIKE:
                countMessage.setLikeOrCollectionCount(0L);
                break;
            case COMMENT:
                countMessage.setCommentCount(0L);
                break;
            case FOLLOW:
                countMessage.setFollowCount(0L);
                break;
        }

        // 持久化到数据库
        this.saveMessageCountToDb(sendUid, type);

        // 更新Redis缓存
        redisUtils.set(messageCountKey, JSONUtil.toJsonStr(countMessage));
    }

    private void updateMessageCountCache(String sendUid, MessageTypeEnum type) {
        String messageCountKey = ImConstant.MESSAGE_COUNT_KEY + sendUid;
        String json = redisUtils.get(messageCountKey);
        if (json != null) {
            CountMessage countMessage = JSONUtil.toBean(json, CountMessage.class);
            switch (type) {
                case CHAT:
                    countMessage.setChatCount(0L);
                    break;
                case PRODUCT_CHAT:
                    countMessage.setProductChatCount(0L);
                    break;
            }
            redisUtils.set(messageCountKey, JSONUtil.toJsonStr(countMessage));
        }
    }

    // 将消息计数持久化到数据库
    private void saveMessageCountToDb(String userId, MessageTypeEnum type) {
//        // 实现消息计数的数据库持久化逻辑
//        MessageCount messageCount = new MessageCount();
//        messageCount.setUserId(userId);
//        messageCount.setType(type.value);
//        messageCount.setCount(0L);
//        messageCount.setUpdateTime(new Date());
//
//        // 使用 saveOrUpdate 更新数据库记录
//        messageCountMapper.saveOrUpdate(messageCount);
    }

    /**
     * 关闭聊天
     *
     * @param sendUid 发送方用户ID
     */
    @Override
    public boolean closeChat(String sendUid) {
        try {
            webSocketServer.onClose(sendUid);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 获取系统通知
     */
    @Override
    public SystemNotification getSystemNotification() {
        // 从Redis获取系统通知，如果不存在则返回默认通知
        String systemNotificationKey = "system:notification";
        String json = redisUtils.get(systemNotificationKey);
        
        if (json != null) {
            try {
                return JSONUtil.toBean(json, SystemNotification.class);
            } catch (Exception e) {
                // 如果解析失败，返回默认通知
            }
        }
        
        // 返回默认系统通知
        return new SystemNotification();
    }

    /**
     * 更新系统通知
     */
    @Override
    public void updateSystemNotification(SystemNotification systemNotification) {
        // 更新Redis中的系统通知
        String systemNotificationKey = "system:notification";
        String json = JSONUtil.toJsonStr(systemNotification);
        redisUtils.set(systemNotificationKey, json);
        
        // 通过WebSocket推送系统通知给所有在线用户
        if (systemNotification.getEnabled()) {
            webSocketServer.sendSystemNotification(systemNotification.getContent());
        }
    }
}
